/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.form; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.*; import java.util.Iterator; import java.util.Hashtable; import org.openide.TopManager; import org.openide.NotifyDescriptor; import org.openide.awt.UndoRedo; import org.openide.filesystems.FileObject; import org.openide.loaders.MultiDataObject; import org.openide.src.nodes.SourceChildren; import org.openide.text.*; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.openide.windows.Workspace; import org.openide.windows.TopComponent; import org.netbeans.modules.java.JavaEditor; /** * * @author Ian Formanek */ public class FormEditorSupport extends JavaEditor implements FormCookie { /** The reference to FormDataObject */ private FormDataObject formObject; /** True, if the design form has been loaded from the form file */ transient private boolean formLoaded = false; /** True, if the form has been opened on non-Editing workspace and shoul dbe opened when the user switches back to Editing */ transient private boolean openOnEditing = false; transient private PropertyChangeListener workspacesListener; private UndoRedo.Manager undoManager; private RADComponentNode formRootNode; private FormManager2 formManager; private PersistenceManager saveManager; private PropertyChangeListener settingsListener; /** lock for opening form */ private static final Object OPEN_FORM_LOCK = new Object (); /** Table of FormManager instances of open forms * @associates FormManager2*/ private static Hashtable openForms = new Hashtable (); private static boolean listenerRegistered = false; private static PropertyChangeListener editorFocusChangeListener = new PropertyChangeListener () { public void propertyChange (PropertyChangeEvent evt) { if (evt.getPropertyName ().equals (TopComponent.Registry.PROP_ACTIVATED)) { TopComponent tc = TopComponent.getRegistry ().getActivated (); if (tc != null) { String componentName = tc.getName (); // is it a form ? => find formManager for it and focus it in ComponentInspector for (java.util.Enumeration enum = openForms.keys (); enum.hasMoreElements ();) { FormEditorSupport fes = (FormEditorSupport) enum.nextElement (); String formName = fes.getFormObject ().getName (); if (formName.equals (componentName)) { FormEditor.getComponentInspector().focusForm ((FormManager2) openForms.get (fes)); break; } } } } } }; public FormEditorSupport (MultiDataObject.Entry javaEntry, FormDataObject formObject) { super (javaEntry); this.formObject = formObject; formLoaded = false; settingsListener = new PropertyChangeListener () { public void propertyChange (PropertyChangeEvent evt) { if (formLoaded) { if (FormLoaderSettings.PROP_INDENT_AWT_HIERARCHY.equals (evt.getPropertyName ())) { formManager.fireCodeChange (); } else if (FormLoaderSettings.PROP_VARIABLES_MODIFIER.equals (evt.getPropertyName ())) { formManager.fireFormChange (); } else if (FormLoaderSettings.PROP_NULL_LAYOUT.equals (evt.getPropertyName ())) { formManager.fireCodeChange (); } } } }; } /** Focuses existing component to open, or if none exists creates new. * @see OpenCookie#open */ public void open () { // status line - Opening form TopManager.getDefault ().setStatusText ( java.text.MessageFormat.format ( NbBundle.getBundle (FormEditorSupport.class).getString ("FMT_OpeningForm"), new Object[] { formObject.getName () } ) ); // load the form synchronized (OPEN_FORM_LOCK) { if (!formLoaded) { if (!loadForm ()) { TopManager.getDefault ().setStatusText (""); // NOI18N return; } } } openForms.put (this, getFormManager ()); if (!listenerRegistered) { TopComponent.getRegistry ().addPropertyChangeListener ( org.openide.util.WeakListener.propertyChange ( editorFocusChangeListener,TopComponent.getRegistry () ) ); listenerRegistered = true; } String fromWorkspace = FormEditor.getFormSettings ().getWorkspace (); if (!fromWorkspace.equalsIgnoreCase (FormEditor.getFormBundle ().getString ("VALUE_WORKSPACE_NONE")) && isCurrentWorkspaceEditing() ) { Workspace visualWorkspace = TopManager.getDefault().getWindowManager().findWorkspace(fromWorkspace); if (visualWorkspace != null) visualWorkspace.activate (); } // 1. show the ComponentInspector boolean isEditingWorkspace = isCurrentWorkspaceEditing (); if (!isEditingWorkspace) attachWorkspacesListener (); // 2. open editor super.open(); // 3. Open and focus form window if (isEditingWorkspace) { getFormTopComponent ().open (); getFormTopComponent ().requestFocus (); } FormEditor.getComponentInspector().focusForm (getFormManager ()); if (isEditingWorkspace) FormEditor.getComponentInspector().open (); // clear status line TopManager.getDefault ().setStatusText (""); // NOI18N } /* Calls superclass. * @param pos Where to place the caret. * @return always non null editor */ protected EditorSupport.Editor openAt(PositionRef pos) { // status line - Opening form TopManager.getDefault ().setStatusText ( java.text.MessageFormat.format ( NbBundle.getBundle (FormEditorSupport.class).getString ("FMT_OpeningForm"), new Object[] { formObject.getName () } ) ); // load the form synchronized (OPEN_FORM_LOCK) { if (!formLoaded) { if (!loadForm ()) { TopManager.getDefault ().setStatusText (""); // NOI18N return super.openAt (pos); } } } String fromWorkspace = FormEditor.getFormSettings ().getWorkspace (); if (!fromWorkspace.equalsIgnoreCase (FormEditor.getFormBundle ().getString ("VALUE_WORKSPACE_NONE")) && isCurrentWorkspaceEditing() ) { Workspace visualWorkspace = TopManager.getDefault().getWindowManager().findWorkspace(fromWorkspace); if (visualWorkspace != null) visualWorkspace.activate (); } // 1. open form window boolean isEditingWorkspace = isCurrentWorkspaceEditing (); if (!isEditingWorkspace) attachWorkspacesListener (); if (isEditingWorkspace) getFormTopComponent ().open (); // 2. show the ComponentInspector FormEditor.getComponentInspector().focusForm (getFormManager ()); if (isEditingWorkspace) FormEditor.getComponentInspector().open (); // 3. Focus form window getFormTopComponent ().requestFocus (); // clear status line TopManager.getDefault ().setStatusText (""); // NOI18N // 4. open editor return super.openAt (pos); } private boolean isCurrentWorkspaceEditing () { String name = TopManager.getDefault ().getWindowManager ().getCurrentWorkspace ().getName (); if (!("Browsing".equals (name) || "Running".equals (name) || "Debugging".equals (name))) { // NOI18N return true; } else { return false; } } private void attachWorkspacesListener () { openOnEditing = true; workspacesListener = new PropertyChangeListener () { public void propertyChange (PropertyChangeEvent evt) { if (WindowManager.PROP_CURRENT_WORKSPACE.equals (evt.getPropertyName ())) { if (openOnEditing) { if (isCurrentWorkspaceEditing ()) { openOnEditing = false; TopManager.getDefault ().getWindowManager ().removePropertyChangeListener (workspacesListener); workspacesListener = null; FormEditor.getComponentInspector().open (); getFormTopComponent ().open (); } } } } }; TopManager.getDefault ().getWindowManager ().addPropertyChangeListener (workspacesListener); } public FormDataObject getFormObject () { return formObject; } public org.openide.nodes.Node getFormRootNode () { return formRootNode; } /** Create an undo/redo manager. * This manager is then attached to the document, and listens to * all changes made in it. * <P> * The default implementation simply uses <code>UndoRedo.Manager</code>. * * @return the undo/redo manager */ protected UndoRedo.Manager createUndoRedoManager () { undoManager = super.createUndoRedoManager (); return undoManager; } UndoRedo.Manager getUndoManager () { return undoManager; } /** @returns the FormManager2 of this form */ public FormManager2 getFormManager () { return formManager; } /** @returns the Form Window */ FormTopComponent getFormTopComponent () { if (!formLoaded) return null; return formManager.getFormTopComponent (); } // ----------------------------------------------------------------------------- // Form Loading protected void notifyClose () { super.notifyClose (); if (!formLoaded) return; if (workspacesListener != null) { TopManager.getDefault ().getWindowManager ().removePropertyChangeListener (workspacesListener); } org.openide.windows.TopComponent formWin = getFormTopComponent (); if (formWin != null) { formWin.setCloseOperation (org.openide.windows.TopComponent.CLOSE_EACH); formWin.close (); } FormEditor.getComponentInspector().focusForm (null); openForms.remove (this); if (openForms.isEmpty ()) { FormEditor.getComponentInspector().close (); } SourceChildren sc = (SourceChildren)formObject.getNodeDelegate ().getChildren (); sc.remove (new RADComponentNode [] { formRootNode }); formRootNode = null; formManager = null; FormEditor.getFormSettings ().removePropertyChangeListener (settingsListener); formLoaded = false; } /** @return true if the form is already loaded, false otherwise */ boolean isLoaded () { return formLoaded; } boolean supportsAdvancedFeatures () { return saveManager.supportsAdvancedFeatures (); } /** @return true if the form is opened, false otherwise */ public boolean isOpened () { return formLoaded; } /** Loads the DesignForm from the .form file. * @return true if the form was correcly loaded, false if any error occured */ protected boolean loadForm () { return loadFormInternal (null); } protected void reloadDocument() { super.reloadDocument (); FormManager2 fm = getFormManager (); fm.getCodeGenerator ().initialize (fm); } /** Loads the DesignForm from the .form file. * @param formTopComponent the top component that the formManager should be initialized with - used during deserialization of workspaces * @return true if the form was correcly loaded, false if any error occured */ protected boolean loadFormInternal (FormTopComponent formTopComponent) { PersistenceManager loadManager = null; for (Iterator it = PersistenceManager.getManagers (); it.hasNext (); ) { PersistenceManager man = (PersistenceManager)it.next (); try { if (man.canLoadForm (formObject)) { loadManager = man; break; } } catch (IOException e) { // ignore error and try the next manager } } if (loadManager == null) { TopManager.getDefault ().notify ( new NotifyDescriptor.Message ( FormEditor.getFormBundle ().getString ("MSG_ERR_NotRecognizedForm"), NotifyDescriptor.ERROR_MESSAGE)); return false; } if (!loadManager.supportsAdvancedFeatures ()) { Object result = TopManager.getDefault().notify( new NotifyDescriptor.Confirmation(FormEditor.getFormBundle ().getString ("MSG_ConvertForm"), NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.QUESTION_MESSAGE) ); if (NotifyDescriptor.YES_OPTION.equals(result)) { saveManager = new GandalfPersistenceManager (); } else { saveManager = loadManager; } } else { saveManager = loadManager; } try { formManager = loadManager.loadForm (formObject); if (formManager == null) { TopManager.getDefault ().notify ( new NotifyDescriptor.Message ( java.text.MessageFormat.format ( FormEditor.getFormBundle ().getString ("FMT_ERR_LoadingForm"), new Object[] { formObject.getName () }), NotifyDescriptor.ERROR_MESSAGE)); return false; } if (formTopComponent != null) { formManager.initFormTopComponent (formTopComponent); } formManager.initialize (); // create form hierarchy node and add it to SourceChildren SourceChildren sc = (SourceChildren)formObject.getNodeDelegate ().getChildren (); formRootNode = new RADComponentNode (formManager.getRADForm ().getTopLevelComponent ()); enforceNodesCreation (formRootNode); sc.add (new RADComponentNode [] { formRootNode }); formLoaded = true; FormEditor.getFormSettings ().addPropertyChangeListener (settingsListener); } catch (Throwable t) { if (t instanceof ThreadDeath) { throw (ThreadDeath)t; } if (System.getProperty ("netbeans.debug.exceptions") != null) { t.printStackTrace (); } TopManager.getDefault ().notify ( new NotifyDescriptor.Message ( java.text.MessageFormat.format ( FormEditor.getFormBundle ().getString ("FMT_ERR_LoadingFormDetails"), new Object[] { formObject.getName (), org.openide.util.Utilities.getShortClassName (t.getClass ()), t.getMessage ()}), NotifyDescriptor.ERROR_MESSAGE)); return false; } // if there are errors or warnings, display it FormEditor.displayErrorLog (); return true; } private void enforceNodesCreation (org.openide.nodes.Node node) { org.openide.nodes.Children ch = node.getChildren (); if (ch != org.openide.nodes.Children.LEAF) { org.openide.nodes.Node[] nodes = ch.getNodes (); for (int i = 0; i < nodes.length; i++) { enforceNodesCreation (nodes[i]); } } } // ----------------------------------------------------------------------------- // Form Saving /** Save the document in this thread and start reparsing it. * @exception IOException on I/O error */ public void saveDocument () throws IOException { super.saveDocument (); saveForm (); } /** Save the document in this thread. * @param parse true if the parser should be started, otherwise false * @exception IOException on I/O error */ protected void saveDocumentIfNecessary(boolean parse) throws IOException { super.saveDocumentIfNecessary(parse); saveForm (); } private void saveForm () { if (formLoaded) { formManager.fireFormToBeSaved (); try { saveManager.saveForm (formObject, formManager); } catch (IOException e) { e.printStackTrace (); } } } // ----------------------------------------------------------------------------- // FormCookie implementation /** Method from FormCookie */ public void gotoEditor() { synchronized (OPEN_FORM_LOCK) { if (!formLoaded) if (!loadForm ()) return; } super.open(); } /** Method from FormCookie */ public void gotoForm() { synchronized (OPEN_FORM_LOCK) { if (!formLoaded) if (!loadForm ()) return; } getFormTopComponent ().open (); getFormTopComponent ().requestFocus (); } } /* * Log * 45 Gandalf 1.44 1/18/00 Pavel Buzek #4348 * 44 Gandalf 1.43 1/12/00 Pavel Buzek I18N * 43 Gandalf 1.42 1/9/00 Pavel Buzek * 42 Gandalf 1.41 1/9/00 Pavel Buzek * 41 Gandalf 1.40 1/9/00 Pavel Buzek #2918 * 40 Gandalf 1.39 1/8/00 Ian Formanek Fixes problem with * corrupted hierarchy in Component Inspector after (re)opening form * 39 Gandalf 1.38 1/5/00 Ian Formanek NOI18N * 38 Gandalf 1.37 12/8/99 Pavel Buzek FormEditor and * ComponentInspector windows open on Visual workspace * 37 Gandalf 1.36 11/24/99 Pavel Buzek Component Inspector is * closed with the last form * 36 Gandalf 1.35 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 35 Gandalf 1.34 9/29/99 Ian Formanek Fixed bug 3853 - * Changing variable Modifier property doesn't force the opened code to be * modified too. * 34 Gandalf 1.33 9/10/99 Ian Formanek Better exception * notification * 33 Gandalf 1.32 9/8/99 Ian Formanek openAt behaves correctly * when form load fails, i18nized * 32 Gandalf 1.31 9/7/99 Ian Formanek Method getFormManager * made public, removed some obsoleted code, improved errors notification * 31 Gandalf 1.30 8/17/99 Ian Formanek Fixed closing forms if * opened on workspace without form * 30 Gandalf 1.29 8/15/99 Ian Formanek Form is opened on * editing workspace only * 29 Gandalf 1.28 8/13/99 Ian Formanek Fixed bug 3253 - Messy * editor when started with more files open. * 28 Gandalf 1.27 8/6/99 Ian Formanek loadFormInternal * 27 Gandalf 1.26 8/1/99 Ian Formanek Fixed potential problem * with closing forms which were not loaded * 26 Gandalf 1.25 7/27/99 Ian Formanek Fixed bug 2638 - Undo in * an editor pane with guarded blocks screws up the guards. * 25 Gandalf 1.24 7/24/99 Ian Formanek Fixed bug with opening * form via class element nodes. * 24 Gandalf 1.23 7/14/99 Ian Formanek supportsAdvancedFeatures * is checked before the form is loaded * 23 Gandalf 1.22 7/12/99 Ian Formanek Notifies form load * exceptions * 22 Gandalf 1.21 7/11/99 Ian Formanek * 21 Gandalf 1.20 7/11/99 Ian Formanek Better work with * persistence managers, supportsAdvancedFeatures added * 20 Gandalf 1.19 7/3/99 Ian Formanek Fires formToBeSaved * before saving... * 19 Gandalf 1.18 6/10/99 Ian Formanek Fixed bug which caused * that forms saved using "Compile" saved only the source and not the form * 18 Gandalf 1.17 6/10/99 Ian Formanek Patched bug which * prevented components to be selecteable by mouse before their nodes were * created * 17 Gandalf 1.16 6/9/99 Ian Formanek ---- Package Change To * org.openide ---- * 16 Gandalf 1.15 5/17/99 Ian Formanek Fixed bug 1820 - An * exception is thrown when form is created from a template. * 15 Gandalf 1.14 5/16/99 Ian Formanek * 14 Gandalf 1.13 5/15/99 Ian Formanek * 13 Gandalf 1.12 5/12/99 Ian Formanek * 12 Gandalf 1.11 5/11/99 Ian Formanek Build 318 version * 11 Gandalf 1.10 5/10/99 Ian Formanek * 10 Gandalf 1.9 5/4/99 Ian Formanek package change * (formeditor -> ..) * 9 Gandalf 1.8 5/2/99 Ian Formanek * 8 Gandalf 1.7 4/29/99 Ian Formanek * 7 Gandalf 1.6 4/29/99 Ian Formanek * 6 Gandalf 1.5 4/12/99 Ian Formanek Improved form loading * debug messages * 5 Gandalf 1.4 4/7/99 Ian Formanek Backward-compatible * deserialization finalized for Gandalf beta * 4 Gandalf 1.3 3/28/99 Ian Formanek * 3 Gandalf 1.2 3/27/99 Ian Formanek * 2 Gandalf 1.1 3/26/99 Ian Formanek * 1 Gandalf 1.0 3/24/99 Ian Formanek * $ */